/**
 * Copyright (C), 1968-2019, 美的集团股份有限公司
 * FileName: UserController
 * Author:   fanyl5
 * Date:     2019/4/20 16:28
 * Description:
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.ruiysoft.crm.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruiysoft.crm.model.dto.*;
import com.ruiysoft.crm.model.entity.SysDept;
import com.ruiysoft.crm.model.entity.SysUser;
import com.ruiysoft.crm.model.entity.SysUserRole;
import com.ruiysoft.crm.model.vo.MenuVO;
import com.ruiysoft.crm.service.SysDeptService;
import com.ruiysoft.crm.service.SysMenuService;
import com.ruiysoft.crm.service.SysUserService;
import com.ruiysoft.crm.model.vo.UserVO;
import com.ruiysoft.crm.service.impl.CommonConstant;
import com.ruiysoft.crm.model.vo.Response;
import com.ruiysoft.crm.service.impl.SecurityConstants;
import com.ruiysoft.crm.util.Query;
import com.ruiysoft.crm.util.TreeUtil;

//import com.ruiysoft.crm.util.common.TreeUtil;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @Description:
 * @author: fanyl5
 * @date: 2019/4/20 16:28
 * @version: 1.0.0
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    SysDeptService sysDeptService;

    @Autowired
    SysUserService sysUserService;

    @Autowired
    private SysUserService userService;

    @Autowired
    private SysMenuService sysMenuService;

    /**
     * 返回当前用户的树形菜单集合
     *
     * @return 当前用户的树形菜单
     */
    @GetMapping(value = "/userMenu")
    public List<MenuTree> userMenu(String roles) {
        if (StringUtils.isEmpty(roles)) {
            return Collections.emptyList();
        }
        // 获取符合条件得菜单
        Set<MenuVO> all = new HashSet<>();
        Arrays.stream(roles.split(",")).forEach(role -> all.addAll(sysMenuService.findMenuByRoleName(role)));
        List<MenuTree> menuTreeList = new ArrayList<>();
        all.forEach(menuVo -> {
            if (CommonConstant.MENU.equals(menuVo.getType())) {
                menuTreeList.add(new MenuTree(menuVo));
            }
        });
        menuTreeList.sort(Comparator.comparing(MenuTree::getSort));
        return TreeUtil.bulids(menuTreeList,-1);

    }

    /**
     * 通过ID查询当前用户信息Å
     *
     * @param id ID
     * @return 用户信息
     */
    @GetMapping("/{id}")
    public UserVO getById(@PathVariable Integer id) {
        return sysUserService.selectUserVoById(id);
    }

    @GetMapping("/info")
    public Response user(Integer userId) {
        UserInfo userInfo = sysUserService.findUserInfo(userId);
        return Response.success(userInfo);
    }

    String createJWT(long ttlMillis, SysUser user) {
        //指定签名的时候使用的签名算法，也就是header那部分，jjwt已经将这部分内容封装好了。
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        //生成JWT的时间
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);

        //创建payload的私有声明（根据特定的业务需要添加，如果要拿这个做验证，一般是需要和jwt的接收方提前沟通好验证方式的）
        Map<String, Object> claims = new HashMap<String, Object>();
        claims.put("id", user.getUserId());
        claims.put("username", user.getUsername());
//        claims.put("password", user.getPassword());

        //生成签名的时候使用的秘钥secret,这个方法本地封装了的，一般可以从本地配置文件中读取，切记这个秘钥不能外露哦。它就是你服务端的私钥，在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。
        String key = user.getPassword();

        //生成签发人
        String subject = user.getUsername();

        //下面就是在为payload添加各种标准声明和私有声明了
        //这里其实就是new一个JwtBuilder，设置jwt的body
        JwtBuilder builder = Jwts.builder()
                //如果有私有声明，一定要先设置这个自己创建的私有的声明，这个是给builder的claim赋值，一旦写在标准的声明赋值之后，就是覆盖了那些标准的声明的
                .setClaims(claims)
                //设置jti(JWT ID)：是JWT的唯一标识，根据业务需要，这个可以设置为一个不重复的值，主要用来作为一次性token,从而回避重放攻击。
                .setId(UUID.randomUUID().toString())
                //iat: jwt的签发时间
                .setIssuedAt(now)
                //代表这个JWT的主体，即它的所有人，这个是一个json格式的字符串，可以存放什么userid，roldid之类的，作为什么用户的唯一标志。
                .setSubject(subject)
                //设置签名使用的签名算法和签名使用的秘钥
                .signWith(signatureAlgorithm, key);
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date exp = new Date(expMillis);
            //设置过期时间
            builder.setExpiration(exp);
        }
        return builder.compact();
    }

    // 123456
    // e10adc3949ba59abbe56e057f20f883e
    String getMD5(String str) {
        if(str == null)
            str = "123456";

        String base = str; // 这里可以加盐
        String md5 = DigestUtils.md5DigestAsHex(base.getBytes());
        return md5;
    }

    /**
     * 分页查询用户
     *
     * @param params 参数集
     * @return 用户集合
     */
    @GetMapping("/userPage")
    public Page userPage(@RequestParam Map<String, Object> params, HttpServletRequest request) {
        String userId = request.getHeader("userId");
        UserVO userVO= sysUserService.selectUserVoById(Integer.parseInt(userId));
        return userService.selectWithRolePage(new Query(params), userVO);
    }

    @GetMapping("/login")
    public Object login(String username, String password, String enterpriseCode) {
        if(StringUtils.isEmpty(enterpriseCode)){
            return Response.failure("请填写企业编号");
        }
      //  SysUser sysUser = sysUserService.getOne(new QueryWrapper<SysUser>().eq("username", username).eq("password", getMD5(password)).eq("enterprise_id",enterpriseId), false);
        SysUser sysUser=sysUserService.login(username,getMD5(password),enterpriseCode);
        if(sysUser != null) {
            String token = createJWT(6000000, sysUser);
            Map<String, Object> map = new HashMap<>();
            map.put("userId", sysUser.getUserId());
            map.put("userName", sysUser.getUsername());
            map.put("enterpriseName", sysUser.getEnterpriseName());
            map.put("enterpriseId", sysUser.getEnterpriseId());
            map.put("access_token", token);

            return Response.success(map);
        }

        return Response.failure("用户名或密码错");
    }

    @GetMapping("/logout")
    public Object logout(String accesstoken) {
        return Response.success();
    }

    /**
     * 获取组织机构及组织机构成员树
     *
     * @param deptId
     * @return
     */
    @GetMapping("/userWithDept")
    public Response queryUserWithDept(@RequestParam(value = "deptId", required = false) Integer deptId) {
        SysDept deptCondition = new SysDept();
        deptCondition.setDelFlag(CommonConstant.STATUS_NORMAL);
        List<SysDept> depts = sysDeptService.list(new QueryWrapper<>(deptCondition));

        SysUser userCondition = new SysUser();
        userCondition.setDelFlag(CommonConstant.STATUS_NORMAL);
        List<SysUser> sysUsers = sysUserService.list(new QueryWrapper<>(userCondition));
        List<UserDTO> users = new ArrayList<>();
        sysUsers.forEach(sysUser -> {
            UserDTO userDTO = new UserDTO();
            BeanUtils.copyProperties(sysUser, userDTO);
            users.add(userDTO);
        });

        //不传deptId,默认使用顶级deptId
        if (ObjectUtils.isEmpty(deptId)) {
            deptId = 0;
        }

        List<DeptAndUserTree> trees = new ArrayList<>();
        DeptAndUserTree node;
        for (SysDept dept : depts) {
            if (dept.getParentId().equals(dept.getDeptId())) {
                continue;
            }
            node = new DeptAndUserTree();
            node.setId(dept.getDeptId());
            node.setParentId(dept.getParentId());
            node.setDeptName(dept.getName());

            List<UserDTO> userList = new ArrayList<>();
            for (UserDTO user : users) {
                if (user.getDeptId().equals(dept.getDeptId())) {
                    userList.add(user);
                }
            }
            node.setUserList(userList);

            trees.add(node);
        }
        List<DeptAndUserTree> result = TreeUtil.buildByRecursive(trees, deptId);
        return Response.success(result);
    }


    /**
     * 删除用户信息
     *
     * @param id ID
     * @return R
     */
    @DeleteMapping("/{id}")
    public Response userDel(@PathVariable Integer id) {
        SysUser sysUser = userService.getById(id);
        if (CommonConstant.ADMIN_USER_NAME.equals(sysUser.getUsername())) {
            return Response.failure("不允许删除超级管理员");
        }
        return Response.success(userService.deleteUserById(sysUser));
    }

    /**
     * 根据部门分组用户数据
     *
     * @return Response
     */
    @GetMapping("/getUsersByDept")
    public Response getUsersByDept(String clientId, HttpServletRequest request) {
        String userId = request.getHeader("userId");
        UserVO userVO= sysUserService.selectUserVoById(Integer.parseInt(userId));

        return Response.success(sysUserService.getUsersByDept(userVO));
    }

    /**
     * 修改个人信息
     *
     * @param userDto userDto
     * @param request  登录用户信息
     * @return success/false
     */
    @PutMapping("/editInfo")
    public Response editInfo(@RequestBody UserDTO userDto, HttpServletRequest request) {
        Integer userId = Integer.parseInt(request.getHeader("userId"));
      //  UserVO userVO= sysUserService.selectUserVoById(Integer.parseInt(userId));
        return userService.updateUserInfo(userDto, userId);
    }

    /**
     * 重制密码
     */
    @PutMapping("/resetPwd")
    public Response resetPwd(@RequestBody UserDTO userDTO ){
        if(org.apache.commons.lang3.StringUtils.isBlank(userDTO.getNewpassword1()))
            userDTO.setNewpassword1("123456");

        return userService.resetPwd(userDTO.getUsername(),userDTO.getNewpassword1());
    }

    /**
     * 更新用户信息
     *
     * @param userDto 用户信息
     * @return R
     */
    @PutMapping
    public Response userUpdate(@RequestBody UserDTO userDto) {
        SysUser user = userService.getById(userDto.getUserId());
        return Response.success(userService.updateUser(userDto, user.getUsername()));
    }

    /**
     * 添加用户
     *
     * @param userDto 用户信息
     * @return success/false
     */
    @PostMapping
    public Response user(@RequestBody UserDTO userDto, HttpServletRequest request) {
        SysUser sysUser = new SysUser();
        Integer userId = Integer.parseInt(request.getHeader("userId"));
        UserVO userVO= sysUserService.selectUserVoById(userId);
        BeanUtils.copyProperties(userDto, sysUser);
        sysUser.setDelFlag(CommonConstant.STATUS_NORMAL);
        sysUser.setEnterpriseId(userVO.getEnterpriseId());
        sysUser.setPassword(getMD5(userDto.getNewpassword1()));

        try {
            userService.save(sysUser);

        } catch (Exception error) {
            return Response.failure(error.getMessage());
        }

        userDto.getRoleList().forEach(role -> {
            SysUserRole userRole = new SysUserRole();
            userRole.setUserId(sysUser.getUserId());
            userRole.setRoleId(role.getRoleId());
            userRole.insert();
        });

        return Response.success(Boolean.TRUE);
    }

}
